#include "cib/cib_connect.hpp"
#include <zephyr/fff.h>
#include <zephyr/ztest.h>
namespace {
struct cib_connect_fixture {
  int i = 0;
  static auto SetUp() -> void * {
    static cib_connect_fixture f;
    return &f;
  }

  static auto Before(void *f) -> void {
    auto fixture = reinterpret_cast<cib_connect_fixture *>(f);
    fixture->i = 0;
  }
};

} // namespace
CIB_SERVICE_DEFINE(TestService, int *)
ZTEST_F(cib_connect, test_one_call) {
  cib::Connect<TestService>([](int *a) { ++(*a); });
  TestService::Call(&fixture->i);
  zassert_equal(fixture->i, 1, "fixture->i = %d", fixture->i);
}

ZTEST_F(cib_connect, test_two_call) {
  constexpr auto f1 = [](int *a) { ++(*a); };
  constexpr auto f2 = [](int *a) { ++(*a); };
  cib::Connect<TestService>(f1, f2);
  cib::CallService<TestService>(&fixture->i);
  zassert_equal(fixture->i, 2, "fixture->i = %d", fixture->i);
}

ZTEST_F(cib_connect, test_muticall_connect) {
  constexpr auto f1 = [](int *a) { ++(*a); };
  constexpr auto f2 = [](int *a) { *a = *a + 2; };
  cib::Connect<TestService>(f1);
  cib::Connect<TestService>(f2);
  cib::CallService<TestService>(&fixture->i);
  zassert_equal(fixture->i, 2, "fixture->i = %d", fixture->i);
}

CIB_SERVICE_DEFINE(TestCallTimes);
DEFINE_FFF_GLOBALS
FAKE_VOID_FUNC(test_call_times_callback);
ZTEST_F(cib_connect, test_call_times) {
  constexpr auto f1 = []() { test_call_times_callback(); };
  constexpr auto f2 = []() { test_call_times_callback(); };
  constexpr auto f3 = []() { test_call_times_callback(); };
  cib::Connect<TestCallTimes>(f1, f2, f3);
  cib::CallService<TestCallTimes>();
  zassert_equal(test_call_times_callback_fake.call_count, 3);
}

#if 0
namespace {

CIB_SERVICE_DEFINE(service_test_connect_features1);
CIB_SERVICE_DEFINE(service_test_connect_features2);
int a3 = 0;

template <typename... TFeatures> struct Project {
  static constexpr auto config = cib::components<TFeatures...>;
};

} // namespace
ZTEST_F(cib_connect, test_connect_features) {
  cib::CallService<service_test_connect_features2>();
  cib::Connect(cib::Extend<service_test_connect_features1>([]() { a3++; },
                                                             []() { a3++; }),
                 cib::Extend<service_test_connect_features2>([]() { a3++; }));
  cib::CallService<service_test_connect_features1>();
  cib::CallService<service_test_connect_features2>();
  zassert_equal(a3, 3, "a3=%d", a3);
}
#endif
ZTEST_SUITE(cib_connect, NULL, cib_connect_fixture::SetUp,
            cib_connect_fixture::Before, NULL, NULL);